package mi.payment.transaction;

import android.text.TextUtils;

import mi.payment.constants.Configs;
import mi.payment.settings.QPSParamsOperation;
import mi.payment.settings.QPSParamsSetting;
import mi.payment.utils.iso8583.Utils;
import sunmi.sunmiui.utils.LogUtil;

/**
 * 双免流程的Controller
 * 符合银联标准的流程
 */
public class BaseQPSFreePwdAndSignController {

    public boolean isFreePassword(String strCardNo, String strAID, long saleAmount, String tag9F6C, String tag9F51, String tagDF71) {
        QPSParamsSetting qpsParamsSetting = QPSParamsOperation.getInstance().getQPSParamsSettings();
        boolean qpsParamCDCVMId = qpsParamsSetting.isQpsParamCDCVMId();
        boolean qpsParamNeedNoPswId = qpsParamsSetting.isQpsParamNeedNoPswId();
        boolean qpsParamBinAId = qpsParamsSetting.isQpsParamBinAId();
        boolean qpsParamBinBId = qpsParamsSetting.isQpsParamBinBId();
        boolean qpsParamBinCId = qpsParamsSetting.isQpsParamBinCId();
        long qpsParamNeedNoPswLimit = qpsParamsSetting.getQpsParamNeedNoPswLimit();

        LogUtil.e(Configs.TAG, "CD CVM标识:" + qpsParamCDCVMId);
        LogUtil.e(Configs.TAG, "非接快速业务标识:" + qpsParamNeedNoPswId);
        LogUtil.e(Configs.TAG, "BIN表A标识" + qpsParamBinAId);
        LogUtil.e(Configs.TAG, "BIN表B标识" + qpsParamBinBId);
        LogUtil.e(Configs.TAG, "BIN表C标识" + qpsParamBinCId);
        LogUtil.e(Configs.TAG, "免密限额:" + qpsParamNeedNoPswLimit);

        // 如果CD CVM开关打开 并且CV CDM已执行 则免密
        boolean judge = qpsParamCDCVMId && isJudgeCVCDM(tag9F6C);
        if (judge) return true; // 免密

        // 启用非接快速业务标识 N1 FF8054
        if (qpsParamNeedNoPswId) {
            judge = isJudgeNeiOrWaiCard(tag9F51, tagDF71); // 判断内卡还是外卡 返回true——内卡 返回false——外卡
            if (judge) { // 卡片为内卡
                if (qpsParamBinAId) {           // 启用BIN表A参数
                    return isUseCardBinA(strCardNo, saleAmount, qpsParamNeedNoPswLimit);
                } else if (qpsParamBinBId) {    // 启用BIN表B参数
                    return isUseCardBinB(strCardNo, strAID, saleAmount, qpsParamNeedNoPswLimit);
                } else if (qpsParamBinCId) {    // 启用BIN表C参数
                    return isUseCardBinC(strCardNo, saleAmount, qpsParamNeedNoPswLimit);
                } else {
                    judge = isDoubleFreeAmountLimit(saleAmount, qpsParamNeedNoPswLimit);
                    if (judge) {
                        LogUtil.e(Configs.TAG, "免密");
                        return true;
                    } else {
                        LogUtil.e(Configs.TAG, "提示输入PIN");
                        return false;
                    }
                }
            } else { // 卡片为外卡
                return isJudgeForeignCard(strAID, saleAmount, qpsParamNeedNoPswLimit, tag9F6C);
            }
        }
        return false;
    }

    public boolean isFreeSign(long saleAmount) { // 非接快速业务（QPS）免签
        QPSParamsSetting qpsParamsSetting = QPSParamsOperation.getInstance().getQPSParamsSettings();
        boolean qpsParamNeedNoSignId = qpsParamsSetting.isQpsParamNeedNoSignId();
        long qpsParamNeedNoSignLimit = qpsParamsSetting.getQpsParamNeedNoSignLimit();
        LogUtil.e(Configs.TAG, "免签标识:" + qpsParamNeedNoSignId);
        LogUtil.e(Configs.TAG, "免签限额:" + qpsParamNeedNoSignLimit);

        // 免签标识
        if (qpsParamNeedNoSignId) {
            boolean judge = isDoubleFreeAmountLimit(saleAmount, qpsParamNeedNoSignLimit); // 限额判断
            if (judge) {
                return true; // 免签
            } else {
                return false; // 需签字
            }
        } else {
            return false;   // 需签字
        }
    }

    public boolean isUseCardBinA(String cardNum, long saleAmount, long limitAmount) {
        LogUtil.e(Configs.TAG, "启用BIN表A参数");
        boolean judge = isJudgeCardBinA(cardNum);
        if (judge) {
            LogUtil.e(Configs.TAG, "BIN表A范围内");
            judge = isDoubleFreeAmountLimit(saleAmount, limitAmount); // 限额判断
            if (judge) {
                LogUtil.e(Configs.TAG, "免密");
                return true;
            } else {
                LogUtil.e(Configs.TAG, "提示输入PIN");
                return false;
            }
        } else {
            LogUtil.e(Configs.TAG, "提示输入PIN");
            return false;
        }
    }

    public boolean isUseCardBinB(String strCardNo, String strAID, long saleAmount, long limitAmount) {
        LogUtil.e(Configs.TAG, "启用BIN表B参数");
        boolean judge = isJudgeDebitOrCreditCard(strAID);
        if (judge) {
            LogUtil.e(Configs.TAG, "BIN-B — DebitCard");
            judge = isJudgeCardBinB(strCardNo);
            if (judge) {
                LogUtil.e(Configs.TAG, "Bin表B范围内");
                judge = isDoubleFreeAmountLimit(saleAmount, limitAmount); // 限额判断
                if (judge) {
                    LogUtil.e(Configs.TAG, "免密");
                    return true;
                } else {
                    LogUtil.e(Configs.TAG, "提示输入PIN");
                    return false;
                }
            } else {
                LogUtil.e(Configs.TAG, "提示输入PIN");
                return false;
            }
        } else {
            LogUtil.e(Configs.TAG, "BIN-B——CreditCard");
            judge = isDoubleFreeAmountLimit(saleAmount, limitAmount); // 限额判断
            if (judge) {
                LogUtil.e(Configs.TAG, "免密");
                return true;
            } else {
                LogUtil.e(Configs.TAG, "提示输入PIN");
                return false;
            }
        }
    }

    public boolean isUseCardBinC(String strCardNo, long saleAmount, long limitAmount) {
        LogUtil.e(Configs.TAG, "启用BIN表C参数");
        boolean judge = isJudgeCardBinC(strCardNo);
        if (judge) {
            LogUtil.e(Configs.TAG, "提示输入PIN");
            return false;
        } else {
            LogUtil.e(Configs.TAG, "BIN C 中没有找到对应的卡BIN");
            judge = isDoubleFreeAmountLimit(saleAmount, limitAmount); // 限额判断
            if (judge) {
                LogUtil.e(Configs.TAG, "免密");
                return true;
            } else {
                LogUtil.e(Configs.TAG, "提示输入PIN");
                return false;
            }
        }
    }

    /**
     * 判断 CV CDM
     * 第1字节位8=“1”，终端应当执行联机PIN校验，不再查询第2字节位8和第1字节位7；
     * 如第1字节位8=“0”，终端应当查询第2字节位8。如第2字节位8=“1”（卡片端CD CVM已执行），终端应认为卡片要求CD CVM作为CVM方式并且已完成校验
     */
    public boolean isJudgeCVCDM(String tag9F6C) {
        if (tag9F6C == null || tag9F6C.length() == 0) return false;
        String str9F6C = Utils.hexStrToBinaryStr(tag9F6C);
        LogUtil.e(Configs.TAG, str9F6C);
        if (str9F6C != null && str9F6C.length() >= 16) {
            // 获取第一个字节的第8位
            String tag1 = str9F6C.substring(0, 1);
            // 获取第二个字节的第8位
            String tag2 = str9F6C.substring(8, 9);
            // 第一个字节的第8位 ==1 执行联机PIN校验
            boolean equals = TextUtils.equals("1", tag1);
            if (equals) {
                return false;
            }
            // 第一个字节的第8位 ==0 并且第二个字节第8位==1 则直接免密
            equals = TextUtils.equals("0", tag1) && TextUtils.equals("1", tag2);
            if (equals) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断内卡还是外卡
     * 返回true——内卡 返回false——外卡
     */
    public boolean isJudgeNeiOrWaiCard(String tag9F51, String tagDF71) {
        boolean judge = TextUtils.isEmpty(tag9F51) && TextUtils.isEmpty(tagDF71);
        if (judge) return true;

        judge = tag9F51.length() > 0 && tag9F51.equals("0156");
        if (judge) return true;

        judge = tagDF71.length() > 0 && tagDF71.equals("0156");
        if (judge) return true;

        return false;
    }

    /**
     * 判断借记卡还是贷记卡
     * 返回true——DebitCard 返回false——CreditCard
     */
    public boolean isJudgeDebitOrCreditCard(String strAID) {
        byte[] byteAID;
        byteAID = Utils.hexStr2Bytes(strAID);
        if (byteAID[byteAID.length - 1] == 0x01) {
            return true;    // 借记卡
        } else {
            return false;   // 贷记卡
        }
    }

    /**
     * 卡片终端协商结果要求Pin
     * 返回true——提示输入PIN 返回false——免密
     */
    public boolean isJudgeNegotiate(String tag9F6C) {
        byte[] byteTag9F6C = Utils.hexStr2Bytes(tag9F6C);
        int var = byteTag9F6C[0] & (byte) 0x80;
        if (var == 1) { // 第1字节位8=“1”，终端应当执行联机PIN校验
            return true;
        } else {
            return false;
        }
    }

    /**
     * 如果渠道还有BIN A 阶段  重写该方法
     * true——卡Bin在BinA表中找到了 false——没有找到
     */
    public boolean isJudgeCardBinA(String cardNum) {
        LogUtil.e(Configs.TAG, "cardNum:" + cardNum);
        String strCardBin = cardNum.length() + cardNum.substring(0, 6);
        String cardBinABuff = "166222111662221216622213166222141662221516622220166222231662222416622225166222291662220616622230166222311662223216622233166222341662223516622236166222371662223816622239166222401662224516622246166225971662259916622910166251601662516116625162166253301662533116625332166256501662570816625709166258581662585916625860166258651662586616625899166282861662828816622210166205141662275216622753166227591662276016622761166227881662583416625333166253371662533816625568166259051662590616625907166259081662590916625910166283121662831316628388196200601962052516621080196210811662108219621284166214661962146716621488166214991962159819621621196216731962170019622280196227001962309416622966166229881962321116623251196236681662595516625956166221681962226019622262166222521662225316622656166282161662821816622285166225881662148316622609166214851662128616621486166231261662313616622575166225761662257716622578166282901662258116622582166258021662580316628362196236991962369819621798196217971962179916625367166253681662597816622685166226871662533916622658166225701662597916622659166259751662265016628201166221611662598116622657166259761662265516628202166228011662260016622601166226021662262316625911166259121662591316625188166217911662179216621793166217951662179616622516166225221662251816621390166213511662252116621352166225231662291616622918166229191662268016622688166226891662820616628208166282091662837016628371166283721662146816621420166231111962055016622889166259001662580116625941166251361662504016625042166250171662501816625019166230741762307418623074196230741662582417625824186258241962582416620136176201361862013619620136";
        boolean contains = cardBinABuff.contains(strCardBin);
        if (contains) {
            LogUtil.e(Configs.TAG, "Find in Bin-A.");
            return true;
        } else {
            LogUtil.e(Configs.TAG, "No Find in Bin-A.");
            return false;
        }
    }

    /**
     * true——卡Bin在BinB表中找到了 false——没有找到
     */
    public boolean isJudgeCardBinB(String cardNum) {
        LogUtil.e(Configs.TAG, "cardNum:" + cardNum);
        String strCardBin = cardNum.length() + cardNum.substring(0, 6);
        String cardBinBuff = QPSParamsOperation.getInstance().getQPSParamsSettings().getCardBinB();
        if (cardBinBuff == null || cardBinBuff.length() == 0)
            return false;
        if (cardBinBuff.contains(strCardBin)) {
            LogUtil.e(Configs.TAG, "Find in Bin-B.");
            return true;
        } else {
            LogUtil.e(Configs.TAG, "No Find in Bin-B.");
            return false;
        }
    }

    /**
     * true——卡Bin在BinC表中找到了 false——没有找到
     */
    public static boolean isJudgeCardBinC(String cardNum) {
        LogUtil.e(Configs.TAG, "cardNum:" + cardNum);
        String strCardBin = cardNum.length() + cardNum.substring(0, 6);
        String cardBinBuff = QPSParamsOperation.getInstance().getQPSParamsSettings().getCardBinC();
        if (cardBinBuff == null || cardBinBuff.length() == 0)
            return false;
        if (cardBinBuff.contains(strCardBin)) {
            LogUtil.e(Configs.TAG, "Find in Bin-C.");
            return true;
        } else {
            LogUtil.e(Configs.TAG, "No Find in Bin-C.");
            return false;
        }
    }

    public boolean isJudgeForeignCard(String strAID, long saleAmount, long limitAmount, String tag9F6C) {
        boolean judge = isJudgeDebitOrCreditCard(strAID); // 判断借记卡还是贷记卡 返回true——DebitCard 返回false——CreditCard
        if (judge) {
            LogUtil.e(Configs.TAG, "借记卡");
            judge = isJudgeNegotiate(tag9F6C); // 卡片终端协商结果要求Pin。返回true——提示输入PIN 返回false——免密
            if (judge) {
                LogUtil.e(Configs.TAG, "提示输入PIN");
                return false;
            } else {
                LogUtil.e(Configs.TAG, "免密");
                return true;
            }
        } else {
            LogUtil.e(Configs.TAG, "贷记卡");
            judge = isDoubleFreeAmountLimit(saleAmount, limitAmount); // 限额判断
            if (judge) {
                LogUtil.e(Configs.TAG, "免密");
                return true;
            } else {
                judge = isJudgeNegotiate(tag9F6C); // 卡片终端协商结果要求Pin。返回true——提示输入PIN 返回false——免密
                if (judge) {
                    LogUtil.e(Configs.TAG, "提示输入PIN");
                    return false;
                } else {
                    LogUtil.e(Configs.TAG, "免密");
                    return true;
                }
            }
        }
    }

    /**
     * 非接快速业务（QPS）限额判断
     */
    public boolean isDoubleFreeAmountLimit(long saleAmount, long limitAmount) {
        if (saleAmount <= limitAmount) {
            // pinState = 1;  // 这里标记内核已经调用输入密码，非接联机函数就不用再输入密码
            return true;
        } else {
            return false;
        }
    }


}
